﻿using System;
using System.IO;

using SharpOSCAR.Base;

namespace SharpOSCAR.Flap
{
    /// <summary>
    /// FLAP provides the packet framing on top of TCP or TLS layer for the OSCAR protocol. 
    /// Each message sent to and from the AIM backend is encapsulated in a FLAP frame that 
    /// is easily identified using a 6 byte header followed by a variable length data segment. 
    /// The payload of a FLAP frame is in most cases a SNAC.
    /// </summary>
    public abstract class FLAP__HEADER : ProtocolData
    {
        private const byte START_MARKER = 0x2A; // *

        private U16 _SequenceNumber;

        /// <summary>
        /// Initializes the FLAP packet with the specified SeqNum
        /// </summary>
        /// <param name="sequenceNumber">Sequence number</param>
        protected FLAP__HEADER(ushort sequenceNumber)
        {
            _SequenceNumber = new U16(sequenceNumber);
        }

        /// <summary>
        /// Gets the frame of the FLAP packet
        /// </summary>
        public abstract FLAP__FRAME_TYPE FrameType { get; }

        /// <summary>
        /// Gets/sets the payload of the FLAP packet
        /// </summary>
        public ProtocolData Payload { get; set; }

        /// <summary>
        /// Converts the FLAP packet into a byte array
        /// </summary>
        /// <returns>Returns a byte array that represents the FLAP packet</returns>
        public override byte[] ToByteArray()
        {
            using (MemoryStream ms = new MemoryStream())
            {
                // Write the start of the header
                ms.WriteByte(START_MARKER);
                ms.WriteByte((byte)FrameType);

                _SequenceNumber.WriteToStream(ms);

                // Get the payload length bytes
                byte[] payload = Payload.ToByteArray();
                U16 payloadLen = new U16(Convert.ToUInt16(payload.Length));
                payloadLen.WriteToStream(ms);

                // If the payload exists, write it to the buffer
                if (payload.Length > 0)
                    Payload.WriteToStream(ms);

                // Return the generated packet
                return ms.ToArray();
            }
        }
    }
}
